/*
 * Entry.java   2008/07/28
 *
 * Copyright 2008 Web & Zen Multimedia, All rights reserved.
 * Use is subject to license terms.
 */
package it.wzm.lightweightlog;

import java.io.Serializable;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;


/**
 * This class is the main wrapper for our error or object we want to log, it is basically
 * a java bean with some getter and setter, and several constructor.
 * It is also implementing few other interfaces:
 * <ul>
 * 	<li>Comparable: to match with other Entries</li>
 * 	<li>Serializable: in future relase serializable will have important role
 * 	<li>Constant: to share global variable
 * </ul>
 * The class also declare XMLAccessorType and XMLType to be used with RemoteDumping
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "entry", namespace = "http://lightweightlogx.wzm.it", propOrder = {
		"timestamp", "message","severity","classname","name","line"
})
public class Entry implements Constant, Comparable<Entry>, Serializable {
    
	/**
	 * As required by serialization
	 */
	public static final long serialVersionUID=-16539879023467L;
    /**
     * The date when the log has been created
     */
    private long timestamp;
    /**
     * The message we want to store
     */
    private String message;
    /**
     * The severity level for this Entry
     */
    private Severity severity;
    /**
     * The classname of the class which cause the error
     */
    private String classname;
    /**
     * The name of the Log
     */
    private String name;
    /**
     * Line holder
     */
    private String line;
    
    /**
     * Public and no-arg constructor as required by Web services.
     */
    public Entry() {    	
    }
    
    /**
     * Construct an Entry from a given set of parameter
     * @param service if True the tag '<service>' will be added before the message
     * @param severity severity
     * @param classname the class that throw the error
     * @param obj The object to log
     */
    protected Entry(String name, Object obj, Severity severity, String classname,long timestamp) {
        // those should never be verified
        assert(severity != null):"Severity null";
        assert(classname != null):"Severity null";
        
        // init...
        this.init(name,obj,severity,classname,timestamp);
    }   
    
    /**
     * Construct an Entry from a given Exception
     * @param service if True the tag '<service>' will be added before the message
     * @param severity severity
     * @param e the Exception to log
     */
    protected Entry(String name, Exception e, Severity severity, long timestamp) {
        // this should never be verified
        assert(severity != null):"Severity null";
        assert(e != null):"Exception null";
                
        // init...
        init(
                name,
                e.getMessage(), // message
                severity,
                e.getCause().getStackTrace()[e.getCause().getStackTrace().length -1].getClassName(), // classname
                timestamp
                );
    }
    
    /**
     * Internal method for init Entry, this method is called by the constructor
     * @param service if True the tag '<service>' will be added before the message
     * @param severity severity
     * @param classname the class that throw the error
     * @param obj The object to log
     */
    private void init(String name, Object obj, Severity severity, String classname, long timestamp) {
        // set basic variable
    	this.setName(name);
        this.setSeverity(severity);
        this.setTimestamp(timestamp);
        this.setClassname(classname);
        
        // check if we pass a null object
        if (obj==null) {
            this.setMessage("null");
        } else {
            this.setMessage(obj.toString());
        }
        
        // the line to be written...
        this.setLine(
        		//new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(this.getTimestamp())
                //DEFAULT_LINE_DATEFORMAT.format(this.getTimestamp())
                //this.getTimestamp()
        		DEFAULT_LINE_DATEFORMAT.format(this.getTimestamp())
                + " "
                + this.getSeverity()
                //+ " - " + this.getName() + " -"
                + " [" + this.getClassname() + "]: "
                + this.getMessage() + "\r\n"
                );        
    }

	/**
     * Getter for Name
     * @return Return Name
     */
    public String getName() {
    	if (name == null)
    		return "";
    	else 
    		return name;
    }
    
    /**
     * Setter for name
     * @param name String
     */
    public void setName(String name) {
        this.name = name;
    }
    
    /**
     * Setter for classname
     * @param classname the classname to set
     */
    public void setClassname(String classname) {
        this.classname = classname;
    }
    
    /**
     * Getter for classname
     * @return classname
     */
    public String getClassname() {
        return classname;
    }
    
    
    /**
     * Build a line of log from the Entry variable example:
     * 2008-07-29 10:22:09 ERROR [it.wzm.common.lightweightlog.client.SampleLog]: err:0
     * @return String
     */
    public String getLine() {
        return this.line;
    }
    
    /**
     * 
     * @param line our line of the log
     */
    public void setLine(String line) {
        this.line=line;
    }
    
    /**
     * Getter for timestamp
     * @return timestamp
     */
    public long getTimestamp() {
        return timestamp;
    }
    /**
     * Setter for timestamp
     * @param timestamp when the Entry has been recorded
     */
    public void setTimestamp(long timestamp) {
        this.timestamp = timestamp;
    }
    
    /**
     * Getter for message
     * @return String
     */
    public String getMessage() {
        return message;
    }
    
    /**
     * Setter for message
     * @param message String
     */
    public void setMessage(String message) {
        this.message = message;
    }
    
    /**
     * Getter for severity
     * @return Severity
     */
    public Severity getSeverity() {
        return severity;
    }
    
    /**
     * Setter for severity
     * @param severity Severity
     */
    public void setSeverity(Severity severity) {
        this.severity = severity;
    }
    
    /**
     * We decide if an Entry is less then another by comparing each timestamp
     * @param e the Entry to compare
     * @return -1, 0, 1 depending...
     */
    public int compareTo(Entry e) {
    	// no way...
        assert(e != null): "Cannot compare null";
        // use double facility...
        return Double.compare(this.getTimestamp(), e.getTimestamp());
    }
    
    /**
     * Overridding from Object
     */
    @Override
    public String toString() {
    	return this.getClass().getName() + "{hc=" + this.hashCode() + ", line(" + this.getLine() + ")}";
    }
    
}

